#!/usr/bin/env bash
#-_-# Yunzai项目管理脚本青春版,详见yunzai-lite --help
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#### 自检
! [[ ${BASH_SOURCE[0]} == $0 ]] && exit 0

#### 字体颜色
## 正常颜色
h01="\033[31m";   # 红
h02="\033[32m";   # 绿
h03="\033[36m";   # 蓝
h04="\033[33m";   # 黄
h07="\033[30m";   # 黑
h09="\033[35m";   # 紫
h10="\033[37m";   # 白
h11="\033[34m";   # 深蓝
## 加粗混色
h13="\033[1;30m"; # 深灰
h14="\033[1;31m"; # 深红
h15="\033[1;32m"; # 亮绿
h16="\033[1;33m"; # 亮黄
h17="\033[1;34m"; # 深蓝
h18="\033[1;35m"; # 暗紫
h19="\033[1;36m"; # 亮蓝
h20="\033[1;37m"; # 浅灰
## 特殊效果
h12="\033[4m";     # 下划线
h06="\033[0m";     # 取消效果
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#### 初始设置
# 是否检测终端尺寸
stty=false
# 脚本主目录
yzcfghome=$BASH_SANDBOX_ROOTDIR/etc/config
# 默认配置文件
defconfig=$yzcfghome/set.conf
# 远程主机登录信息
sshcfg=$yzcfghome/ssh.conf
# watch dog通行开关，true为开
dog=false
# 是否启用一言
yiyan=false
# 版本号
versions=3.9.1
# 更新时间
times=2024/04/17
# 是否启用交互插件，如果已安装的话
TUI=false
# Yunzai默认位置
yzpath=$HOME/Yunzai-Bot
# 项目名称，为管理器提供统一称呼和克隆路径
name=Yunzai-Bot
# 默认ffmpeg源地址
ffmpeg=https://gitee.com/yunxiyuan/yxybot/releases/download/ffmpeg
# 项目合集
indexURL=https://gitee.com/yhArcadia/Yunzai-Bot-plugins-index
# 项目索引数据
yunzai_app_data=$BASH_SANDBOX_ROOTDIR/etc/data/yunzai.install.list.json
# github代理加速
proxy=("ghproxy.net" "mirror.ghproxy.com" "github.moeyy.xyz")
source /etc/os-release

#### 初始化
if [ ! -f $defconfig ];then
  sets
fi
if [ -f $defconfig ];then
  source $defconfig
  name=$(awk -F/ '{print $NF}' <<< $yzpath)
fi

if [[ -f $yzpath/lib/bot.js && -f $yzpath/app.js ]];then
  isbot=true
else
  isbot=false
fi

## 判断终端宽度
${stty:-false} && ! [[ $1 == set ]] && [[ $(tput cols) < 66 ]] && echo -e "终端界面过窄\n请调整终端宽度至\n66或以上" && exit

#### 判断系统架构
case $(uname -m) in
  aarch64)arm=arm64;;
  aarch32)arm=arm32;;
  x86_32)arm=x86;;
  x86_64)arm=x64;;
  *)arm=Null
esac
if [ $arm = arm32 ] || [ $arm = x86 ];then
  wran "32位机型或发行版系统支持较少，不推荐使用"
  exit 127
elif [ $arm = Null ];then
  wran "未知的设备或发行版系统架构，无法使用"
  exit 127
fi

issue=$(kfc print.release ID_LIKE)
case $issue in
  debian)os=1;;
  arch)os=2;;
  fedora)os=3;;
  alpine)echo "不受支持的发行版";exit;;
  termux)echo "不受支持的终端环境";exit;;
  *)echo "未知的发行版 $issue"
esac

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#### 加载函数
# 颜色
color(){
    case $1 in
        num)
            [[ $2 =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]] && printf "\e[38;5;%d;m" ${2} || echo -e "\033[0mcolor: 8-BitColor: “(Num:$2)”: 这不是一个合法的或不在范围内的色值"
        ;;
        rgb)
            [[ $2 =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\,){2}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]] && printf "\e[38;2;%d;%d;%d;m" $(echo $2 | sed "s/\,/\ /g") || echo -e "\033[0mcolor: TrueColor: “(R:$(echo $2 | sed "s/\,/ G\:/;s/\,/ B\:/"))”: 这不是一个合法的RGB色值"
    esac
}

# 获取时间戳
gettime(){
    getdate=$(date -d "0.435 second" +%H:%M:%S.%N)
    echo "${getdate: 0: -6}"
}

# 日志前缀
king(){
    echo -e "${h02}[小吉祥草王] ${h06}$@"
}
main(){
    echo -e "[Yzlite][$(gettime)]"
}

# 日志
err(){
    echo -e "${h01}$(main)[ERRO] ${h06}$@"
}
log(){
    echo -e "${h02}$(main)[INFO] ${h06}$@"
}
warn(){
    echo -e "${h04}$(main)[WARN] ${h06}$@"
}
mark(){
    echo -e "\e[38;2;127;127;127m$(main)[MARK] ${h06}$@"
}

# 计算器
cll(){
    awk "BEGIN{print $@}" 2>/dev/null
}

#计时器
s_time(){
    start_time=$(date +%s.%N)
}
e_time(){
    end_time=$(date +%s.%N)
    printf %.2f $(cll ${end_time}-${start_time})
}

# 判断命令
ifapp(){
    [ -z $(command -v $1) ] && err "未安装${2:-$1}，无法满足运行要求" && exit
}

# 读取配置
setting(){
    [ -z $1 ] && exit
    [ -z $2 ] && exit
    timeout 3 grep -E "^${1}=." $2 | sed "s/^${1}=//g"
}

# 网络判断
wlan(){
    if [[ $(ip a | grep inet | wc -l) == 2 ]]; then
        err "请连接网络"
        exit 1
    fi
}

# 一言
yiyan(){
    [[ $(setting yiyan $defconfig) == "true" ]] && wlan && hitokoto=$(curl -sLm3 https://v1.hitokoto.cn/?encode=json) && hitokoto_one=$(printf "%s" ${hitokoto} | sed 's@,@\n@g' | grep 'hitokoto.*:' | awk -F '"' '{print $4}' | sed 's@^@“@' | sed 's@$@”@') && hitokoto_author=$(printf "%s" ${hitokoto} | sed 's@,@\n@g' | grep -v 'commit_from' | grep 'from.*:' | awk -F '"' '{print $4}' | sed '/null,/d' | tr '\n' ' ') && echo -e "${hitokoto_author}: ${hitokoto_one}"
}

# 寻找 Yunzai
findyz(){
    help="用法: findyz [根路径] [递归层数: 默认2]\n用于搜索Yunzai项目根目录";
    [ -z $(command -v node) ] && echo 'findyz: 未安装nodejs' && exit;
    [ -z $1 ] && echo -e "$help" && exit 0;
    [ $1 == "/" ] && warn "findyz: 不得为根目录" && exit 0;
    [[ $1 =~ ^(-)?(h|help)$ ]] && echo -e "$help" && exit 0;
    [ ! -z $2 ] && [[ ! $2 =~ ^[0-9]+$ ]] && echo 'findyz: 参数[2]: 必须为纯数字' && exit;
    [ ! -z $2 ] && [[ $2 -lt 1 || $2 -gt 16 ]] && echo 'findyz: 参数[2]: 要求不低于1 且不高于16' && exit;
    node -e "const findyz = (directory, depth = 2) => { if (depth === 0) { return [];}; const files = fs.readdirSync(directory);const results = [];for (const file of files) { const filePath = path.join(directory, file);if (fs.lstatSync(filePath).isDirectory()) { if (filePath.indexOf('node_modules') === -1) { results.push(...findyz(filePath, depth - 1));}} else { if (fs.lstatSync(filePath).isFile() && file.includes('package.json')) { const content = fs.readFileSync(filePath, 'utf-8');const json = JSON.parse(content);const name = json.name;if (name && name.includes('yunzai')) { results.push(filePath);}}}}return results;};const fds = results => { for (const result of results) { console.log(result.slice(0, -13));}};const main = async () => {const directory = '$1';const depth = '${2:-2}';const results = await findyz(directory, depth);fds(results);};main();"
}

# 进程管理
poss(){
    if [ ! -z $(pgrep "[Yy]un(zai)?") ]; then
        YzID="$(ps -p "$(pgrep "[Yy]un(zai)?")" -o comm=)";
    else
        YzID=Null;
    fi;
    if [ "${YzID}" == "Null" ]; then
        mark "未检测到相关进程...";
        exit 0;
    fi;
    [[ $YzID =~ 'yunzai-menu' ]] && return 0;
    inpid="$(pidof "${YzID}")";
    pkill PM2;
    pkill node;
    pkill -2 $YzID > /dev/null;
    pkill redis-server;
    echo;
    warn "已强制终止相关进程\n$(mark)进程名: ${h02}${YzID}${h06}\n$(mark)进程号: ${h02}${inpid}${h06}"
}

yzapps(){
    for i in $@;
    do
        command -v $i || echo Null;
    done
}
yzset(){
    for i in $@;
    do
        setting $i $defconfig || echo Null;
    done
}
sets(){
    echo -e "# 是否检测终端尺寸\nstty=$stty\n\n# WIFI_watch_dog\ndog=$dog\n\n# 使用yunzai时是否启用交互插件\nTUI=$TUI\n\n# 一言\nyiyan=true\n\n# Yunzai本地地址\nyzpath=$yzpath\n\n# 默认FFmpeg镜像源\nffmpeg=$ffmpeg\n\n# Yunzai相关项目合集\nindexURL=$indexURL" > $defconfig
}

# 软件管理
pkg_install(){
    debian="apt install -y"
    arch="pacman -S --noconfirm"
    fedora="dnf install -y"
    termux="pkg install -y"
    case $ID_LIKE in
        debian | arch | fedora)
            if [[ ! -z $1 && $1 == --print-arg ]]; then
                printf "${!ID_LIKE}"
            else
                ${!ID_LIKE} $@
            fi
        ;;
    esac
}
pkg_remove ()
{
    debian="apt remove -y"
    arch="pacman -R --noconfirm"
    fedora="dnf remove -y"
    termux="pkg remove -y"
    case $ID_LIKE in
        debian | arch | fedora)
            if [[ ! -z $1 && $1 == --print-arg ]]; then
                printf "${!ID_LIKE}"
            else
                ${!ID_LIKE} $@;
            fi
    esac
}
pkg_search(){
    debian="apt search"
    arch="pacman -Si"
    fedora="dnf search"
    termux="pkg search"
    case $ID_LIKE in
        debian | arch | fedora)
            if [[ ! -z $1 && $1 == --print-arg ]]; then
                printf "${!ID_LIKE}"
            else
                ${!ID_LIKE} $@
            fi
    esac
}
pkg_update(){
    debian="apt update -y"
    arch="pacman -Sy --noconfirm"
    fedora="dnf update -y"
    termux="pkg update -y"
    case $ID_LIKE in
        debian | arch | fedora)
            if [[ ! -z $1 && $1 == --print-arg ]]; then
                printf "${!ID_LIKE}"
            else
                ${!ID_LIKE}
            fi
    esac
}
pkg_upgrade(){
    debian="apt upgrade -y"
    arch="pacman -Syu --noconfirm"
    fedora="dnf upgrade -y"
    termux="pkg upgrade -y"
    case $ID_LIKE in
        debian | arch | fedora)
            if [[ ! -z $1 && $1 == --print-arg ]]; then
                printf "${!ID_LIKE}"
            else
                ${!ID_LIKE} $@
            fi
    esac
}
ins(){
    [ -z $1 ] && echo '未指定要求检查的软件包' && exit;
    if [ ! $(command -v $1) ]; then
        log "正在安装: $1";
        if ! pkg_install $1; then
            err "$1: 安装失败！";
            exit 1;
        fi;
        log "$1: 安装完成";
    else
        mark "$1: 软件已存在";
    fi
}
inss(){
    [ -z $1 ] && echo '未指定要求检查的软件包' && exit;
    if [ ! $(command -v $1) ]; then
        log "正在安装: $1";
        if ! pkg_install $1; then
            err "$1: 安装失败！";
            exit 1;
        fi;
        log "$1: 安装完成";
    fi
}

YzApp=($(yzapps yunzai-list yunzai-menu yunzai-api yunzai-file))
theplugin=${YzApp[0]}
themenu=${YzApp[1]}
theapi=${YzApp[2]}
thefile=${YzApp[3]}

#### 主模块
case $1 in

-ih|ih|-hi|hi)$0 -i -h;;
-iy|iy|-yi|yi)$0 install -y ${@: 2};;
-il|il|-li|li)$0 -i -l;;
-lj|-jl|lj|jl)$0 -l js;;
-lp|-pl|lp|pl)$0 -l plugin;;
-ic|ic|-ci|ci)$0 -i -c ${@: 2};;
-im|im|-mi|mi)$0 -i -m ${@: 2};;
-icy|icy|-ciy|ciy|-yic|yic|-iyc|iyc|-cyi|cyi)$0 -i -c ${@: 2} -y;;
-imy|imy|-miy|miy|-yim|yim|-iym|iym|-myi|myi)$0 -i -m -y ${@: 3};;
-ia|ia|-ai|ai)$0 -i add;;
-ib|ib|-bi|bi)$0 -i --Bot $2;;

-h*|h*|--h*)
echo -e \
"用法: $(basename $0) [选项] [选项|行为] [行为] ...\n"\
"必选选项对长短选项同样适用，在某些情况下不可缺少行为目的\n"\
"           选项                            描述\n"\
" -l --list <plugin|js>             查看${name}安装的插件\n"\
" -O --occupy                       查看${name}占用空间\n"\
" -s --start                        启动${name}\n"\
" -i --install <选项>               详细用法请用[ -h ]参数\n"\
" -R --remove <名称>                卸载指定plugin|${name}\n"\
" -r --run <名称>                   调用内置函数[实验性的]\n"\
" -S --set <选项>                   项目设置\n"\
" -I --index                        项目资源索引页\n"\
" -h --help                         打印本帮助信息并退出\n"\
" -v --version                      打印版本并退出"
yiyan;;

-s*|s*|--s*)
  log "请稍等..."
  mark "测试网络连接..."
  if [[ ! $(ip a | grep inet | wc -l) = 2 ]];then
    log "网络连接通过测试"
  else
    err "请连接网络"
    exit 1
  fi
  if [ $dog = "true" ];then
    if [[ $(($(ps -ef|grep YUNZAI_WLAN_WATCH_DOG|awk '{print $2}'|wc -l) - 1)) = 0 ]];then
      $0 YUNZAI_WLAN_WATCH_DOG &
      mark "看门狗已启动，将在断开网络后强制 ${name} 停车"
    fi
  fi
  process=$(pgrep "[Yy]un(zai)?")
  if [[ ! -z $process && ! $(ps -p "$process" -o comm=) =~ 'yunzai-menu'  ]];then
    poss
    mark "已终止${name}的进程，如欲继续使用请重新执行启动命令"
    exit
  fi
  if [ -d $yzpath ];then
    if [ $(command -v redis-server) ];then
      redis=$yzpath/config/config/redis.yaml
      redis_port=$(grep port: $redis | awk '{print $2}')
      redis-server \
        --daemonize yes \
        --save 900 1 \
        --save 300 10 \
        --port $redis_port \
        --ignore-warnings ARM64-COW-BUG \
          >/dev/null &&
      mark "redis已启动 端口: $redis_port"
    else
      err "redis未安装!"
      exit 1
    fi
  if [ ! $(command -v node) ];then
    err "nodejs未安装!"
    exit 1
  fi
  cd $yzpath
  cfg=$yzpath/config/config/qq.yaml
  defcfg=$yzpath/config/default_config/qq.yaml
  if [ -f $cfg ];then
    bot=$(grep platform: $redis | awk '{print $2}')
    case "${bot}" in
      1)from=Android_Phone;;
      2)from=Android_Pad;;
      3)from=Android_Watch;;
      4)from=MacOS;;
      5)from=iPad;;
      6)from=Android;;
      *)from=Null
    esac
    mark "${name}启动中，将尝试使用${from}协议登录..."
  else
    if [ -f $defcfg ];then
      mark "未找到${cfg}，这可能是首次启动"
    else
      mark "${name}启动中..."
      yiyan
    fi
  fi
    export NODE_OPTIONS=--no-deprecation
    node app
  else
    err "请确认$yzpath路径未改动或是否安装了${name}，亦或者是否正确安装/设定了${name}"
  fi
  unset NODE_OPTIONS;;

-l*|l*|--l*)
  if [ ! ${isbot} = true ];then
    err "项目不存在或无法正确识别项目"
    exit 1
  fi
  if [ -z $2 ] 2> /dev/null;then
    err "请在命令处一同输入<plugin>或<js>"
  else
    if [ $2 == plugin ] 2> /dev/null;then
      log "来自 $yzpath/plugins 的发现:"
      for i in `ls -d $yzpath/plugins/*/ | grep -v 'genshin\|system\|other\|example\|bin\|adapter'`;do
        dirname $(ls ${i}*.js 2>/dev/null | grep 'index.js') 2>/dev/null | awk -F/ '{print $NF}'
      done | while IFS= read -r line; do
        echo "$line"
      done
    elif [ $2 == "js" ] 2>/dev/null;then
      log "来自 $yzpath/plugins 的发现:"
      for i in `ls -d $yzpath/plugins/*/ | grep -v 'genshin\|system\|other\|adapter'`;do
        ls ${i}*.js 2>/dev/null | grep -v 'guoba.support.js\|index.js\|main.js'
      done | while IFS= read -r line; do
        echo "[$(basename $(dirname $line 2>/dev/null))][$(basename $line 2>/dev/null)]"
      done
    else
      err "请输入正确的参数"
      exit 0
    fi
  fi;;

-O*|o*|--o*|-o*)
  if [ ! ${isbot} = true ];then
    err "项目不存在，拒绝运行"
    exit 1
  fi
  king "请稍等,正在统计${name}的空间占用..."
  sleep 0.5
  s_time
  king "${name}的空间占用为${h02}$(agg cll.size 1024 $(du -sb $yzpath | awk '{print $1}'))${h06}"
  log "用时$(e_time)秒";;

R*|-R*|rm|--remove|-rm|u*q)
  if [ -z $2 ];then
    err "请指定目标"
    exit 1
  fi
  case $2 in
    -j*|--j*|--J*|-J*)
      if [ -z $3 ];then
        err "请指定目标"
        exit 1
      fi
      if [ $(grep '.js' <<< $3) ];then
        jsname=$3
      else
        jsname=${3}.js
      fi
      if [ -z $4 ];then
        warn "未指定分组，将从默认分组(example)寻找js文件"
        jsdir=example
      else
        jsdir=$4
      fi
      if [ ! -f $yzpath/plugins/$jsdir/$jsname ];then
        err "未找到指定js文件($jsname)，试试换个分组？"
        exit 1
      fi
      if rm $yzpath/plugins/$jsdir/${jsname};then
        log "删除完成，祝你使用愉快"
      else
        err "删除失败，请重试！"
        exit 1
      fi;;
    -B*|--B*|--b*|-b*|b*)
      if [ $isbot = true ];then
        htr="我同意并允许删除$name，我愿意承受所有后果"
        warn "这将删除整个${name}！包括已安装的所有plugin！"
        warn "在删除前请输入：${h01}${htr}${h06}"
        read -p '请输入: ' htr1
        if  [ ${htr} == ${htr1} ];then
          mark "正在删除..."
          rm -rf $yzpath/ &&
          mark "删除完成，祝你使用愉快" ||
          err "删除失败" && exit 1
        else
          err "输入错误或不同意"
          exit 1
        fi
      else
        err "${name}: 项目不存在"
        exit 1
      fi;;
    *)
      if [[ $2 =~ ^(example|genshin|other|system|adapter)$ ]];then
        err "$2: 不允许删除"
        exit 1
      elif [ -d $yzpath/plugins/$2 ];then
        warn "是否删除$2？"
        read -p '[Y/n]: ' nt
        case $nt in
        N|n)mark "已退出删除";exit 0;;
        Y|y)mark "开始删除...";s_time
          if rm -rf $yzpath/plugins/$2/;then
            log "删除完成，用时$(e_time)秒，祝你使用愉快"
          else
            err "删除失败"
            exit 1
          fi;;
        *)
          if [ -z $nt ];then
            nt=Null
          fi
          err "${nt}: 意料之外的选项"
          exit 1
        esac
      else
        if [ ${2: 0: 1} = '-' ];then
          err "yunzai: rm: $2: 意外的选项"
        else
          shopt -s nocasematch
          findplugin=($(ls $yzpath/plugins/ | grep -iw "$2"))
          if [[ ${#findplugin[@]} = 1 ]];then
            err "$2: 不存在的plugin\n你可能预想的目标：\n${h03}$findplugin${h06}"
          else
            err "$2: 不存在的plugin"
        fi
      fi
      exit 1
    fi
  esac;;

  i*|-i*|--i*)
    if [ ! -f ${theplugin} ];then
      err "未安装扩展库，拒绝运行"
      exit 1
    fi
    wlan
    if [ -z $2 ];then
      err "请指定目标，欲知详细用法请使用命令:\n${h02}yunzai install help${h06}"
      exit 1
    fi
  case $2 in
    --h*|-h*|h*)
      echo -e \
        "用法: yunzai install [选项]\n"\
        "此为yunzai的项目安装功能[install]\n"\
        " -A --add           检索软件并安装\n"\
        " -B --Bot           安装${name}\n"\
        " -l --list          查看可安装的plugin\n"\
        " -c --custom        从指定URL安装plugin|jsfile\n"\
        " -m --multi         连续安装指定plugin\n"\
        " -y --yes           跳过询问\n"\
        " <名称>             安装指定plugin\n";;

    -l*|l*|--l*)
     arr=($(yunzai-list --all))
     arrn=($(yunzai-list --all-name))
     prev_letter=""
     for ((i=0; i<${#arr[@]}; i++)); do
       _name_=${arr[$i]}
       current_letter=$(awk '{print substr($1, 1, 1)}' <<< "$_name_")
       [[ $i = 0 ]] && echo -e \
         "按[${h02}Q${h06}]键离开界面 按[${h02}↑${h06}][${h02}↓${h06}]键/鼠标滚轮/触屏上下滑动翻阅\n"\
         "使用方法：yunzai install [插件名] ...\n"\
         " $h02[@]$h06 共计$h02[${#arr[@]}]$h06个Plugin项目"
         if [[ $current_letter =~ [a-zA-Z] ]]; then
           if [ "${current_letter^}" != "${prev_letter^}" ];then
           echo -e " $h16[${current_letter^}]──────────────────────────────────\n $h06 │"
           prev_letter="$current_letter"
         fi
       else
         if [ -n "$prev_letter" ];then
           echo -e " $h16[#]──────────────────────────────────$h06\n  │"
            prev_letter=""
          fi
         fi
       echo -e \
          "  $([[ $(($i + 1)) != ${#arr[@]} ]]&&echo ├||echo └) 项目"\
          "$h03[$((i + 1))]$h19 $_name_\n"\
          "  $([[ $(($i + 1)) != ${#arr[@]} ]]&&echo │||echo " ")$([ $(($i + 1)) -gt 9 ]&&echo " ")      └$h02[#]$h09 名称: $h04${arrn[$i]}插件$h06\n $([[ $(($i + 1)) != ${#arr[@]} ]]&&echo " │")"
        done | less -Rm;;

      -B*|--B*|B*|--b*|-b*|b*)
        if [ ! $(command -v git) ];then
          err "未安装git，已终止进程"
          exit 1
        fi
        yunzai_search_list=($(yunzai-list -A))
        [ -z $3 ] && log "仓库中收录了以下项目:\n${yunzai_search_list[@]}\n使用 $(basename $0) install bot [项目名称] 以安装项目" && exit 0
        yunzai_search=($(yunzai-list -S $3))
        [[ $yunzai_search == Null ]] &&
        err "不存在的项目" && exit 1
        [[ $yunzai_search == "这是彩蛋啦^_^" ]] &&
        log "这是彩蛋啦^_^" && exit 0
        if [ ! -d $HOME/${yunzai_search[1]} ];then
          log "正在克隆${yunzai_search[1]}..."
          s_time
          [[ ! -z ${yunzai_search[4]} ]] && yzgit="-b ${yunzai_search[4]}" || yzgit=''
          if git clone $yzgit  https://${yunzai_search[0]} $HOME/${yunzai_search[1]};then
            log "克隆完成，用时$(e_time)秒"
          else
            err "来自${h03}${yunzai_search[0]}${h06}: 拉取失败"
            exit
          fi
        else
          warn "已存在${yunzai_search[1]}, 位于: $HOME/${yunzai_search[1]}"
          exit 127
        fi
        if [ ! $(command -v node) ];then
          err "未安装node，已终止进程"
          exit 1
        fi
        if [ ! $(command -v pnpm) ];then
          err "未安装pnpm，已终止进程"
          exit 1
        fi
        if `jq ".[\"Bots\"][\"${yunzai_search[1]}\"] | has(\"command\")" $yunzai_app_data`;then
          log "检索到项目预设命令，获取命令数据"
          jq -r ".[\"Bots\"][\"${yunzai_search[1]}\"][\"command\"][]" $yunzai_app_data | while IFS= read -r line; do
            log "执行命令: $line"
            eval $line
          done
        fi
        if [ ! -d $HOME/${yunzai_search[1]}/node_modules ];then
          log "检测无modules，尝试安装"
          s_time
          pnpm install -P --prefix $HOME/${yunzai_search[1]} &&
          log "node_modules 安装完成" ||
          err "node_module 安装失败"
          mark "任务用时$(e_time)秒"
        fi
        if `jq ".[\"Bots\"][\"${yunzai_search[1]}\"] | has(\"plugins\")" $yunzai_app_data`;then
          log "检索到附加项，获取数据中"
          jq -r ".[\"Bots\"][\"${yunzai_search[1]}\"][\"plugins\"][]" $yunzai_app_data | while IFS= read -r line; do
            log "为 ${yunzai_search[1]} 安装插件: $line"
            installPlugin=($(yunzai-list $line))
            url=${installPlugin[0]}
            plugin=${installPlugin[1]}
            model=${installPlugin[2]}
            if [ ! -d $HOME/${yunzai_search[1]}/plugins/${plugin} ];then
              mark "准备克隆${plugin}..."
              if [[ $url =~ ^github.* ]];then
                log "这是一个github项目。"
                url=${proxy[${xy: -0}]}/$url
                log "使用代理: https://${proxy[${xy: -0}]}/"
              fi
              s_time
              if ! git clone --depth=1 https://${url}.git $HOME/${yunzai_search[1]}/plugins/${plugin};then
                err "${plugin}: 拉取失败"
                exit 1
              else
                log "${plugin}: 克隆完成，用时$(e_time)秒"
              fi
              if [[ ${model} == off ]];then
                mark "${plugin}: 该plugin无模块需要。"
              elif [ ${model} = auto ];then
                if [ -f $HOME/${yunzai_search[1]}/plugins/$plugin/package.json ];then
                  mark "${plugin}: package.json: 发现有独立模块需安装，执行中..."
                  s_time
                  if yes | pnpm i --prefix $HOME/${yunzai_search[1]}/plugins/$plugin/;then
                    log "${plugin}: 独立模块安装完成，用时$(e_time)秒"
                  else
                    err "${plugin}: 独立模块安装失败"
                    mark "正在删除 ${plugin} ..."
                    s_time
                    if rm -rf $HOME/${yunzai_search[1]}/plugins/$plugin/;then
                      log "删除完成，用时$(e_time)秒"
                    else
                      err "删除失败"
                    fi
                    exit
                  fi
                else
                  mark "${plugin}: 该plugin无模块需要。"
                fi
              else
                mark "${plugin}: 发现有附加模块需安装，推荐:${model}，执行中..."
                s_time
                if yes | pnpm install ${model} -w --prefix $HOME/${yunzai_search[1]};then
                  log "${model}: 安装完成，用时$(e_time)秒"
                else
                  err "${model}: 安装失败，请检查项目是否支持开发者权限"
                  exit 1
                fi
              fi
            else
              warn "${plugin}: 该plugin已存在"
            fi
          done
        fi
        mark "是否允许设置为默认项目?"
        read -p "[Y/n]: " nt
        case $nt in
          N|n)mark "取消";exit 0;;
          Y|y)$0 -S yzpath $HOME/${yunzai_search[1]};;
          *)
            if [ -z $nt ];then
              nt=Null
            fi
            err "${nt}: 意料之外的选项"
            exit 1
          esac;;

      -y)
        if [ -z $3 ];then
          bash ${BASH_SOURCE[0]} install
        else
          if [ -z $4 ];then
            bash ${BASH_SOURCE[0]} install $3 -y
          else
            bash ${BASH_SOURCE[0]} install $3 $4 -y
          fi
        fi;;

      add)
        mark "检查更新所有软件..."
        pkg_update
        log "完成。\n$(mark)检查安装所需软件..."
        ins git
        ins curl
        ins wget
        ins pv
        ins jq
        ins yq
        if [ ! $(command -v redis-server) ];then
          log "正在安装: redis"
          if ! pkg_install redis;then
            err "redis: 安装失败！"
            exit 1
          fi
          log "redis: 安装完成"
        else
          mark "redis: 软件已存在"
        fi
        ins chromium
        if [ ! $(command -v ffmpeg) ];then
          log "正在安装: ffmpeg"
          if [[ $os == 2 ]];then
            pkg_install ffmpeg
            ffmpeg
          else
            if ! pkg i ffmpeg;then
              err "ffmpeg: 安装失败！请检查源地址！"
              exit 1
            fi
            chmod 755 /usr/local/bin/ffmpeg
            ffmpeg
          fi
          log "ffmpeg: 安装完成"
        else
          mark "ffmpeg: 软件已存在"
        fi
        if [ ! $(command -v node) ];then
          log "正在安装: node"
          if [[ ! $os == 2 ]];then
            if ! curl -sL https://deb.nodesource.com/setup_21.x | bash;then
              err "软件源设置失败"
              exit 1
            fi
          fi
          if ! pkg_install nodejs-lts-iron;then
            err "node: 安装失败！"
            exit 1
          fi
          log "node: 安装完成"
          else
          mark "node: 软件已存在"
        fi
        if [ ! $(command -v pnpm) ];then
          log "正在安装: pnpm"
          if [[ $os == 2 ]];then
            if ! kfc fn.yay pnpm;then
              err "pnpm: 安装失败！"
              exit 1
            fi
          else
            if ! npm install pnpm -g;then
              err "pnpm: 安装失败！"
              exit 1
            fi
          fi
          log "pnpm: 安装完成"
        else
          mark "pnpm: 软件已存在"
        fi
        case $os in
          1)
            if [ ! -d /usr/share/fonts/truetype/wqy ];then
              log "正在安装所需字体库: 文泉驿微黑"
              pkg_install fonts-wqy-microhei
              pkg_install ttf-wqy-microhei
              log "文泉驿微黑: 已载入字体库"
            else
              mark "该字体已存在"
            fi;;
          2)
            if [ ! -d /usr/share/fonts/wenquanyi ];then
              log "正在安装所需字体库: 文泉驿正黑"
              pkg_install wqy-bitmapfont wqy-zenhei ttf-arphic-ukai ttf-arphic-uming
              log "文泉驿正黑: 已载入字体库"
            else
              mark "文泉驿正黑: 该字体已存在"
            fi;;
          3)
            if [ ! -d /usr/share/fonts/truetype/chinese ];then
              log "正在安装所需字体库: 中文"
              pkg_install fonts-chinese fonts-chinese.noarch epel-release
              log "中文: 已载入字体库"
            else
              mark "中文: 该字体已存在"
            fi;;
          esac
        log "检查完成。";;

      multi|--multi|-multi|-m|m)
        if [ ! ${isbot} = true ];then
          err "项目不存在，拒绝运行"
          exit 1
        fi
        if [ -z $3 ];then
          err "请指定一个或以上目标"
          exit 1
        fi
        if [ $3 = -y ] && [ -z $4 ];then
          err "请指定一个或以上目标"
          exit 1
        fi
       case $3 in
         -y|yes|--yes|-yes)
           $0 install --multi $(sed 's/\-y//g' <<< ${@: 3}) -y;;
         *)
           if [ ! ${!#} = -y  ]||[ ! ${!#} = -yes  ]||[ ! ${!#} = --yes  ]||[ ! ${!#} = yes  ];then
             echo -e "${h03}${@: 3}${h06}"
             mark "是否允许安装以上plugin?"
             read -p "[Y/n]: " nt
             case $nt in
               N|n)mark "已退出安装";exit 0;;
               Y|y)log "开始安装...";;
               *)
                 if [ -z $nt ];then
                   nt=Null
                 fi
                 err "${nt}: 意料之外的选项"
                 exit 1
               esac
             fi
             for mpsl in $(sed 's/\-y//g' <<< ${@: 3}); do
               $0 install $mpsl -y
             done
             exit 0;;
           esac;;

      -c|custom|--custom|-custom)
        case $3 in
          -y)
            if [ -z $4 ];then
              $0 install -c
            else
              $0 install -c $4 $5 -y
            fi;;
          *)
            if [ ! ${isbot} = true ];then
              err "项目不存在，拒绝运行"
              exit 1
            fi
            if [ -z $3 ];then
              err "请指定目标"
              echo '用法: $(basename $0) install custom [URL] [files] -y'
              exit 0
            fi
            if [ ! ${!#} = -y ];then
              log "是否继续执行?"
              read -p "[Y/n]: " nt
              case $nt in
                N|n)mark "已退出";exit 0;;
                Y|y)mark "开始执行...";;
                *)
                  if [ -z $nt ];then
                    nt=Null
                  fi
                  err "${nt}: 意料之外的选项"
                  exit 1
                esac
              fi
              if [ ! $(command -v curl) ];then
                err "未安装curl"
                exit 1
              fi
              if [ ! $(command -v git) ];then
                err "未安装git"
                exit 1
              fi
              if [ ! $(command -v node) ];then
                err "未安装node"
                exit 1
              fi
              if [ ! $(command -v pnpm) ];then
                err "未安装pnpm"
                exit 1
              fi
              url=$3
              mark "测试网址连通性..."
              if [[ $url =~ ^github.* ]];then
                log "这是一个github项目。"
                url=${proxy[${xy: -0}]}/$url
                log "使用代理: https://${proxy[${xy: -0}]}/"
              fi
              if [[ $(curl -s -w %{http_code} $url) == 404 ]];then
                err "连接异常: 404"
                exit 1
              elif [[ $(curl -s -w %{http_code} $url) == 403 ]];then
                err "连接异常: 403"
                exit 1
              fi
              if [ ${url: 0-3} = ".js" ];then
                mark "该链接可能是某一个后缀为“.js”的插件的源地址"
                if [ $4 = '-y' ] && [ -z $5 ];then
                  mark "未指定js插件安装位置，将安装在默认分组（example）"
                  jsdir=example
               else
                 jsdir=$4
               fi
               if [[ $3 = *\/blob\/* ]];then
                 jsurl=$(sed 's#/blob/#/raw/#g' <<< $url)
                 mark "网址非源文件，已纠正为: \n${h12}${jsurl}${h06}"
               else
                 jsurl=$url
               fi
               jsname=`echo $jsurl | awk -F/ '{print $NF}'`
               newname=$(sed 's/%/\\x/g' <<< $jsname)
               if [ -f $yzpath/plugins/$jsdir/"$(echo -e $newname)" ];then
                 mark "$newname: 该插件已存在"
                 exit 127
               fi
               s_time
               if wgets "$jsurl" > "$yzpath/plugins/example/$newname";then
                 log "下载完成，已下载到: \n${h03}$yzpath/plugins/$jsdir/$newname${h06}   用时$(e_time)秒"
               else
                 err "下载失败"
                 exit 1
               fi
             elif [ ${url: 0-4} = ".git" ];then
               mark "该链接可能是某一个plugin的源地址"
               pnames=(`sed 's/-y//g' <<< $@`)
               purls=$(awk -F/ '{print $NF}' <<< $url)
               if [ -z $4 ];then
                mark "未指定plugin名称，将从网址字段中截取可能的名称..."
                pn=$(echo $purls | sed 's/.git//g')
                log "可能的plugin名称: $pn"
              else
                pn=$4
              fi
              if [ -d $yzpath/plugins/$pn ];then
                mark "$pn: 该plugin已存在"
                exit 0
              fi
              mark "正在克隆: $pn"
              s_time
              if git clone --depth=1 $url $yzpath/plugins/$pn;then
                log "$pn: 克隆完成，用时$(e_time)秒"
              else
                err "$pn: 克隆失败"
                exit 1
              fi
              if [ -f $yzpath/plugins/$pn/package.json ];then
                mark "$pn: 发现可安装的模块，尝试安装..."
                s_time
                if yes | pnpm i -P --prefix $yzpath/plugins/$pn;then
                log "模块安装完成，用时$(e_time)秒"
              else
                err "模块安装失败"
                exit
              fi
            fi
          else
            mark "无法识别的类型"
          fi;;
       esac;;

     *)
       if [ ! ${isbot} = true ];then
         err "项目不存在，拒绝运行"
         exit 1
       fi
       installPlugin=($(yunzai-list $2))
       if [ ${installPlugin} = null ];then
         err "$2: 该plugin未记录在库或不存在"
         exit 1
       fi
       if [ ! ${!#} = -y ];then
         mark "是否安装$2?"
         read -p "[Y/n]: " nt
         case $nt in
         N|n)log "已退出安装";exit 0;;
         Y|y)mark "开始安装...";;
         *)
           if [ -z $nt ];then
             nt=Null
           fi
           err "${nt}: 意料之外的选项"
           exit 1
         esac
       fi
       url=${installPlugin[0]}
       plugin=${installPlugin[1]}
       model=${installPlugin[2]}
       if [ ! -d $yzpath/plugins/${plugin} ];then
         mark "准备克隆${plugin}..."
         if [[ $url =~ ^github.* ]];then
           log "这是一个github项目。"
           url=${proxy[${xy: -0}]}/$url
           log "使用代理: https://${proxy[${xy: -0}]}/"
         fi
         s_time
         if ! git clone --depth=1 https://${url}.git $yzpath/plugins/${plugin};then
         err "${plugin}: 拉取失败"
         exit 1
       else
         log "${plugin}: 克隆完成，用时$(e_time)秒"
       fi
       if [ ${model} = off ];then
         mark "${plugin}: 该plugin无模块需要。"
       elif [ ${model} = auto ];then
         if [ -f $yzpath/plugins/$plugin/package.json ];then
           mark "${plugin}: package.json: 发现有独立模块需安装，执行中..."
           s_time
           if yes | pnpm i --prefix $yzpath/plugins/$plugin/;then
             log "${plugin}: 独立模块安装完成，用时$(e_time)秒"
           else
             err "${plugin}: 独立模块安装失败"
             mark "正在删除 ${plugin} ..."
             s_time
             if rm -rf $yzpath/plugins/$plugin/;then
               log "删除完成，用时$(e_time)秒"
             else
               err "删除失败"
             fi
             exit 1
           fi
         else
           mark "${plugin}: 该plugin无模块需要。"
         fi
       else
         mark "${plugin}: 发现有附加模块需安装，推荐:${model}，执行中..."
         s_time
         if yes | pnpm install ${model} -w --prefix $yzpath;then
           log "${model}: 安装完成，用时$(e_time)秒"
         else
           err "${model}: 安装失败，请检查项目是否支持开发者权限"
           exit 1
         fi
       fi
     else
       warn "${plugin}: 该plugin已存在"
     fi;;
  esac;;

  -S|set|--set|-set)
    if [ ! -f $defconfig ];then
     err "找不到配置文件"
     exit 1
    fi
    apex=0
    if [ -z $2 ];then
      echo -e "$h19##Setting##$h06\n$(sed "s/^/\\\033[32m/g;s/=/\\\033[36m=\\\033[33m/g;s/#/\\\033[1\;35m#/g;s/$/\\\033[0m/g" $defconfig)\n\n$h13位置: $defconfig$h06\n\n按[${h02}Q${h06}]键离开界面" | less -R
      let apex++
    else
      for i in $(cat $defconfig|grep -o '.*='|tr -d "="); do
        h=$(setting $i $defconfig | sed 's/\//\\\//g')
        d=$(sed -n "/^$i/=" $defconfig)
        r=$(echo $3 | sed 's/\//\\\//g')
        if [ $2 == $i ];then
          let apex++
          if [ -z $3 ];then
            setn=$2
            log "当前$setn的设置项为${!setn}"
            exit 1
          fi
          if [ $r == $h ];then
            warn "$2: 重复的设置"
            exit 127
          else
            if [[ ${!2} =~ ^(false|true)$ ]]&&[[ ! $3 =~ ^(false|true)$ ]];then
              warn "$2: 新的设置并非布尔值"
              mark "如有需求请修改：$h03${defconfig}$h06"
              exit 0
            elif [[ ! ${!2} =~ ^(false|true)$ ]]&&[[ $3 =~ ^(false|true)$ ]];then
              warn "$2: 新的设置不得为布尔值"
              mark "如有需求请修改：$h03${defconfig}$h06"
              exit 0
            fi
            sed -i "${d}s/$h/$r/" $defconfig
            log "已将$i的规则更新为$3"
            exit 0
          fi
        fi
      done
    fi
    if [ $apex == 0 ];then
      err "$2: 未知的选项"
      exit 1
    fi;;

  -I|index|--index|-index)
    mark "网址:\n${h03}${h12}${indexURL}${h06}";;

    YUNZAI_WLAN_WATCH_DOG)
      if [ ! ${isbot} = true ];then
        err "项目不存在，拒绝运行"
        exit 1
      fi
      while true; do
        if [ -f $defconfig ];then
          watchdog=$(setting dog $defconfig)
        else
          watchdog=$(setting dog $0)
        fi
        if [ $watchdog = true ];then
          if [[ $(ip a | grep inet | wc -l) = 2 ]];then
            echo
            err "检测到WALN已断开，尝试终止${name}的进程..."
            poss
            unset NODE_OPTIONS
            exit 127
          fi
        else
          warn "看门狗检测状态更新，尝试回收进程..."
          unset NODE_OPTIONS
          exit 0
        fi
      done;;

  r|-r|-rf|run|--run|-run|--run-function)
    function=(`grep -o '^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*(){' $0 | tr -d '(){}'`)
    function=($(for i in "${function[@]}"; do echo $i; done | sort))
    if [ -z $2 ];then
      echo -e "可供调用的函数有:\n${function[@]}\n共计[$h02${#function[@]}$h06]个函数"
      exit 0
    fi
   j=0
   for i in ${function[@]};do
     if [[ $i == $2 ]];then
       let j++
     fi
   done
   if [[ $j == 1 ]];then
     $2 "${@: 3}"
   else
     echo -e "yunzai: $2: 不是一个函数"
   fi;;

  -v)echo -e "v${versions}";;

  *)[ ! -z $1 ] && echo "$(basename $0): $1: 找不到用法"
esac